package org.fujene.index;

import org.fujene.structure.ContentInfo;
import org.msgpack.MessagePackObject;
import org.msgpack.object.ArrayType;
import org.msgpack.object.BooleanType;
import org.msgpack.object.IntegerType;
import org.msgpack.object.RawType;

public class IndexingPackage{
	private int cluster;
	private long ID;
	private String[] contents;
	private String[] appendices;
	private boolean[] binaryFlags;
	private int[] multipleFlags;

	// Use it normally, from content information
	public IndexingPackage(ContentInfo contentInfo){
		this.contents = new String[contentInfo.contentsNum()];
		this.appendices = new String[contentInfo.appendixNum()];
		this.binaryFlags = new boolean[contentInfo.binaryFlagNum()];
		this.multipleFlags = new int[contentInfo.multipleFlagNum()];
	}

	// Use it for reverting from log file
	public IndexingPackage(int contentlen, int appendixlen, int binaryFlaglen, int multipleFlaglen){
		this(0, contentlen, appendixlen, binaryFlaglen, multipleFlaglen);
	}

	// Use locally to make package from messagepack message
	public IndexingPackage(long ID, int contentlen, int appendixlen, int binaryFlaglen, int multipleFlaglen){
		this.ID = ID;
		this.contents = new String[contentlen];
		this.appendices = new String[appendixlen];
		this.binaryFlags = new boolean[binaryFlaglen];
		this.multipleFlags = new int[multipleFlaglen];
	}

	public static IndexingPackage makePackage(ArrayType packedMessage){
		MessagePackObject[] objs = packedMessage.asArray();
		if(objs.length < 5) return null;
		IndexingPackage pkg =
			new IndexingPackage(objs[0].asLong(), objs[1].asInt(), objs[2].asInt(), objs[3].asInt(),
				objs[4].asInt());

		int index = 5;
		for(int i = 0; i < pkg.contents.length; i++)
			pkg.contents[i] = objs[index + i].asString();
		index += pkg.contents.length;
		for(int i = 0; i < pkg.appendices.length; i++)
			pkg.appendices[i] = objs[index + i].asString();
		index += pkg.appendices.length;
		for(int i = 0; i < pkg.binaryFlags.length; i++){
			if(objs[index + i].asBoolean()) pkg.binaryFlags[i] = objs[index + i].asBoolean();
		}
		index += pkg.binaryFlags.length;
		for(int i = 0; i < pkg.multipleFlags.length; i++)
			pkg.multipleFlags[i] = objs[index + i].asInt();

		return pkg;
	}

	public ArrayType makeRemoteContentObject(){
		MessagePackObject[] contentObjs =
			new MessagePackObject[contents.length + appendices.length + binaryFlags.length
				+ multipleFlags.length + 5];
		contentObjs[0] = IntegerType.create(ID);
		contentObjs[1] = IntegerType.create(contents.length);
		contentObjs[2] = IntegerType.create(appendices.length);
		contentObjs[3] = IntegerType.create(binaryFlags.length);
		contentObjs[4] = IntegerType.create(multipleFlags.length);

		int index = 5;
		for(int i = 0; i < contents.length; i++)
			contentObjs[index + i] = RawType.create(contents[i]);
		index += contents.length;
		for(int i = 0; i < appendices.length; i++)
			contentObjs[index + i] = RawType.create(appendices[i]);
		index += appendices.length;
		for(int i = 0; i < binaryFlags.length; i++)
			contentObjs[index + i] = BooleanType.create(binaryFlags[i]);
		index += binaryFlags.length;
		for(int i = 0; i < multipleFlags.length; i++)
			contentObjs[index + i] = IntegerType.create(multipleFlags[i]);

		return ArrayType.create(contentObjs);
	}

	public IndexingPackage setCluster(int index){
		this.cluster = index;
		return this;
	}

	public IndexingPackage setID(long ID){
		this.ID = ID;
		return this;
	}

	public IndexingPackage setContent(String content, int index){
		this.contents[index] = content;
		return this;
	}

	public IndexingPackage setAppendix(String appendix, int index){
		this.appendices[index] = appendix;
		return this;
	}

	public IndexingPackage setBinaryFlag(boolean flag, int index){
		this.binaryFlags[index] = flag;
		return this;
	}

	public IndexingPackage setMultipleFlag(int flag, int index){
		this.multipleFlags[index] = flag;
		return this;
	}

	public int cluster(){
		return cluster;
	}

	public long ID(){
		return ID;
	}

	public String content(int index){
		return this.contents[index];
	}
	
	public String[] contents() {
		return this.contents;
	}

	public int contentLength(){
		return this.contents.length;
	}

	public String appendix(int index){
		return this.appendices[index];
	}
	
	public String[] appendices() {
		return this.appendices;
	}

	public int appendixLength(){
		return this.appendices.length;
	}
	
	public boolean[] binaryFlags() {
		return this.binaryFlags;
	}

	public boolean binaryFlag(int index){
		return this.binaryFlags[index];
	}

	public int binaryFlagLength(){
		return this.binaryFlags.length;
	}

	public int binaryFlagArraySize(){
		return (this.binaryFlags.length % 8 == 0 ? this.binaryFlags.length / 8 : this.binaryFlags.length / 8 + 1);
	}

	public int multipleFlag(int index){
		return this.multipleFlags[index];
	}
	
	public int[] multipleFlags() {
		return this.multipleFlags;
	}

	public int multipleFlagLength(){
		return this.multipleFlags.length;
	}
}
